package reporting

import (
	"bytes"
	"fmt"
	"text/template"
	"time"

	"github.com/SAP/jenkins-library/pkg/orchestrator"

	"golang.org/x/text/cases"
	"golang.org/x/text/language"
)

// VulnerabilityReport represents metadata for a report on a vulnerability
type VulnerabilityReport struct {
	ProjectName          string
	ProjectVersion       string
	BlackDuckProjectLink string
	ArtifactID           string
	Branch               string
	CommitID             string
	Description          string
	DependencyType       string
	Footer               string
	Group                string
	PackageURL           string
	PipelineName         string
	PipelineLink         string
	PublishDate          string
	Resolution           string
	Score                float64
	Severity             string
	Version              string
	VulnerabilityLink    string
	VulnerabilityName    string
	Origin               string
}

const vulnerabilityMdTemplate string = `# {{title .Severity }} ({{ .Score }}) Vulnerability {{ .VulnerabilityName }} - {{ .ArtifactID }}

**Vulnerability link:** [{{ .VulnerabilityLink }}]({{ .VulnerabilityLink }})

{{if .Resolution -}}
## Fix

**{{ .Resolution }}**
{{- end}}

## Context

{{if .PipelineLink -}}
### Pipeline

Pipeline run: [{{ .PipelineName }}]({{ .PipelineLink }})
{{- end}}

### Detected in

**Project Version:** [{{ .ProjectName }} {{ .ProjectVersion }}]({{ .BlackDuckProjectLink }})
{{if .Branch}}**Branch:** {{ .Branch }}{{- end}}
{{if .CommitID}}**CommitId:** {{ .CommitID }}{{- end}}
{{if .Group}}**Group:** {{ .Group }}{{- end}}
{{if .PublishDate}}**Publishing date:** {{.PublishDate }}{{- end}}

{{if .ArtifactID}}**ArtifactId:** {{ .ArtifactID }}{{- end}}
{{if .Version}}**Version:** {{ .Version }}{{- end}}
{{if .Origin}}**Origin:** {{ .Origin }}{{- end}}
{{if .DependencyType}}**Dependency:** {{ .DependencyType }}{{- end}}
{{if .PackageURL}}**Package URL:** {{ .PackageURL }}{{- end}}

## Description

{{ .Description }}

---

{{.Footer}}
`

// ToMarkdown creates a vulnerability in markdown format which can be used in GitHub issues
func (v *VulnerabilityReport) ToMarkdown() ([]byte, error) {
	funcMap := template.FuncMap{
		"date": func(t time.Time) string {
			return t.Format("2006-01-02")
		},
		"title": func(s string) string {
			caser := cases.Title(language.AmericanEnglish)
			return caser.String(s)
		},
	}

	// only fill with orchestrator information if orchestrator can be identified properly
	if provider, err := orchestrator.GetOrchestratorConfigProvider(nil); err == nil {
		// only add information if not yet provided
		if len(v.CommitID) == 0 {
			v.CommitID = provider.CommitSHA()
		}
		if len(v.PipelineLink) == 0 {
			v.PipelineLink = provider.JobURL()
			v.PipelineName = provider.JobName()
		}

		if len(v.Branch) == 0 {
			v.Branch = provider.Branch()
		}
	}

	md := []byte{}
	tmpl, err := template.New("report").Funcs(funcMap).Parse(vulnerabilityMdTemplate)
	if err != nil {
		return md, fmt.Errorf("failed to create  markdown issue template: %w", err)
	}
	buf := new(bytes.Buffer)
	err = tmpl.Execute(buf, v)
	if err != nil {
		return md, fmt.Errorf("failed to execute markdown issue template: %w", err)
	}
	md = buf.Bytes()
	return md, nil
}
